import functools
from collections.abc import Iterator

from fastapi import Depends, FastAPI
from sqlalchemy.ext.asyncio import AsyncSession

from recruit.adapter.database.db import (
    create_async_session_maker,
    create_async_session,
)
from recruit.adapter.database.gateway import UserGateway, ResumeAboutUsGateway, ResumeGateway
from recruit.adapter.stubs import StubUserGateway, StubResumeAboutUsGateway, StubResumeGateway
from recruit.application.protocols import UoW
from recruit.core.config import load_database_config
from recruit.presentation.dependencies.depends_stub import Stub


def new_uow(
        session: AsyncSession = Depends(Stub(AsyncSession)),
) -> AsyncSession:
    return session


def new_user_gateway(
        session: AsyncSession = Depends(Stub(AsyncSession))
) -> Iterator[UserGateway]:
    yield UserGateway(session)


# TODO: Cover tests
def new_resume_about_us_gateway(
        session: AsyncSession = Depends(Stub(AsyncSession))
) -> Iterator[ResumeAboutUsGateway]:
    yield ResumeAboutUsGateway(session)


def new_resume_gateway(
        session: AsyncSession = Depends(Stub(AsyncSession))
) -> Iterator[StubResumeGateway]:
    yield ResumeGateway


def init_dependencies(app: FastAPI) -> None:
    db_url = load_database_config().db_url
    session_maker = create_async_session_maker(db_url)
    app.dependency_overrides.update(
        {
            AsyncSession: functools.partial(
                create_async_session,
                session_maker
            ),
            UoW: new_uow,
            StubUserGateway: new_user_gateway,
            StubResumeAboutUsGateway: new_resume_about_us_gateway,
            StubResumeGateway: new_resume_gateway
        }
    )
